package imp

import (
	sqlc "bgs/db/sqlc"
	brandDistributorGrpc "bgs/grpc/gen/service/brand_distributor"
	"bgs/grpc/gen/shared/message"
	"bgs/util"
	"context"
	"fmt"
)

/****************************************************************************************/
/*                               brand_distributor entity of helper                       */
/****************************************************************************************/

func transformBrandDistributorEntityToPb(o sqlc.BrandDistributor) *brandDistributorGrpc.BrandDistributorEntity {
	return &brandDistributorGrpc.BrandDistributorEntity{
		Id:                      o.ID,
		UserId:                  o.UserID,
		BrandId:                 o.BrandID,
		AliasName:               o.AliasName,
		Became:                  sqlc.GoTimeToPBTimestamp(o.Became),
		Remark:                  o.Remark.String,
		DistributeActivityCount: o.DistributeActivityCount,
		SaleAmount:              o.SaleAmount,
	}
}

func mapBrandDistributorEntityToPb(list []sqlc.BrandDistributor, f func(sqlc.BrandDistributor) *brandDistributorGrpc.BrandDistributorEntity) []*brandDistributorGrpc.BrandDistributorEntity {
	r := make([]*brandDistributorGrpc.BrandDistributorEntity, len(list))
	for i, item := range list {
		r[i] = f(item)
	}
	return r
}

/****************************************************************************************/
/*                               brand_distributor entity of cmd                          */
/****************************************************************************************/

// UpdateBrandDistributor 更新品牌分销员
func (s *BrandAPIService) UpdateBrandDistributor(ctx context.Context, req *brandDistributorGrpc.UpdateBrandDistributorRequest) (res *brandDistributorGrpc.UpdateBrandDistributorResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brand_distributorImp->UpdateBrandDistributor:%v", req)
	res = &brandDistributorGrpc.UpdateBrandDistributorResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	arg := sqlc.UpdateBrandDistributorParams{
		ID:        req.Id,
		AliasName: req.AliasName,
		Remark:    sqlc.NSFromString(req.Remark),
	}
	BrandDistributor, err := s.dao.Q.UpdateBrandDistributor(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.BrandDistributor = transformBrandDistributorEntityToPb(BrandDistributor)
	return
}

// CancelBrandDistributor 取消品牌分销员(deprecated)
func (s *BrandAPIService) CancelBrandDistributor(ctx context.Context, req *brandDistributorGrpc.CancelBrandDistributorRequest) (res *brandDistributorGrpc.CancelBrandDistributorResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brand_distributorImp->CancelBrandDistributor:%v", req)
	res = &brandDistributorGrpc.CancelBrandDistributorResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	var BrandDistributor sqlc.BrandDistributor

	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {

		BrandDistributor, err = q.DisableBrandDistributor(ctx, req.Id)
		if err != nil {
			return err
		}
		slog.Info("1 disable brand_distributor ok")

		total, err := q.CountNormalBrandDistributorsByUserID(ctx, BrandDistributor.UserID)
		if err != nil {
			return err
		}
		slog.Infof("2 CountBrandDistributorsByUserID=>%d", total)

		if total == 0 {
			user, err := q.GetUser(ctx, BrandDistributor.UserID)
			if err != nil {
				return err
			}
			slog.Info("3 获取user ok")
			userRoles := user.Roles

			newUserRoles := util.StringFilter(userRoles, func(s string) bool {
				return s != string(sqlc.EmUserRoleBrandDistributor)
			})
			user, err = q.UpdateUserRoles(ctx, sqlc.UpdateUserRolesParams{
				ID:    BrandDistributor.UserID,
				Roles: newUserRoles,
			})
			if err != nil {
				return err
			}
			slog.Info("4 更新用户roles ok")
		}

		return
	})
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.BrandDistributor = transformBrandDistributorEntityToPb(BrandDistributor)
	return
}

/****************************************************************************************/
/*                            brand_distributor entity of query                           */
/****************************************************************************************/

// GetBrandDistributor 获取单个品牌分销员
func (s *BrandAPIService) GetBrandDistributor(ctx context.Context, req *brandDistributorGrpc.GetBrandDistributorRequest) (res *brandDistributorGrpc.GetBrandDistributorResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brand_distributorImp->GetBrandDistributor:%v", req)
	res = &brandDistributorGrpc.GetBrandDistributorResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	brandDistributor, err := s.dao.Q.GetBrandDistributor(ctx, req.Id)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.BrandDistributor = transformBrandDistributorEntityToPb(brandDistributor)
	return
}

// ListNormalBrandDistributorsByBrandID  获取正常的品牌分销员列表
func (s *BrandAPIService) ListNormalBrandDistributorsByBrandID(ctx context.Context, req *brandDistributorGrpc.ListNormalBrandDistributorsByBrandIDRequest) (res *brandDistributorGrpc.ListNormalBrandDistributorsByBrandIDResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brand_distributorImp->ListNormalBrandDistributorsByBrandID:%v", req)

	res = &brandDistributorGrpc.ListNormalBrandDistributorsByBrandIDResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	total, err := s.dao.Q.CountNormalBrandDistributorsByBrandID(ctx, req.BrandId)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	if total == 0 {
		// 不用继续调用listfunc
		return
	}
	arg := sqlc.ListNormalBrandDistributorsByBrandIDParams{
		Limit:   req.Limit,
		Offset:  req.Offset,
		BrandID: req.BrandId,
	}
	brandDistributors, err := s.dao.Q.ListNormalBrandDistributorsByBrandID(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.Total = total
	res.BrandDistributors = mapBrandDistributorEntityToPb(brandDistributors, transformBrandDistributorEntityToPb)
	return
}

/****************************************************************************************/
/*                            brand_distributorJoins entity of helper                     */
/****************************************************************************************/

func transformBrandDistributorWithUserEntityToPb(row sqlc.ListNormalBrandDistributorWithUsersByBrandIDRow) *brandDistributorGrpc.BrandDistributorWithUserEntity {
	return &brandDistributorGrpc.BrandDistributorWithUserEntity{
		// brand_admin
		Id:                      row.ID,
		UserId:                  row.UserID,
		BrandId:                 row.BrandID,
		AliasName:               row.AliasName,
		Became:                  sqlc.GoTimeToPBTimestamp(row.Became),
		Remark:                  row.Remark.String,
		DistributeActivityCount: row.DistributeActivityCount,
		SaleAmount:              row.SaleAmount,
		// user
		DistributorUserNickName: row.DistributorUserNickName,
		DistributorUserPic:      row.DistributorUserPic,
		// stat
		FansCount: row.FansCount,
	}
}

func mapBrandDistributorWithUserEntityToPb(list []sqlc.ListNormalBrandDistributorWithUsersByBrandIDRow, f func(sqlc.ListNormalBrandDistributorWithUsersByBrandIDRow) *brandDistributorGrpc.BrandDistributorWithUserEntity) []*brandDistributorGrpc.BrandDistributorWithUserEntity {
	r := make([]*brandDistributorGrpc.BrandDistributorWithUserEntity, len(list))
	for i, item := range list {
		r[i] = f(item)
	}
	return r
}

func transformListNormalBrandDistributorWithBrandsByUserIDRowEntityToPb(row sqlc.ListNormalBrandDistributorWithBrandsByUserIDRow) *brandDistributorGrpc.BrandDistributorWithBrandEntity {
	return &brandDistributorGrpc.BrandDistributorWithBrandEntity{
		// brand_admin
		Id:        row.ID,
		UserId:    row.UserID,
		BrandId:   row.BrandID,
		AliasName: row.AliasName,
		Became:    sqlc.GoTimeToPBTimestamp(row.Became),
		Remark:    row.Remark.String,
		// brand
		BrandName: row.BrandName,
		BrandPic:  row.BrandPic.String,
	}
}

func mapListNormalBrandDistributorWithBrandsByUserIDRowEntityToPb(list []sqlc.ListNormalBrandDistributorWithBrandsByUserIDRow, f func(sqlc.ListNormalBrandDistributorWithBrandsByUserIDRow) *brandDistributorGrpc.BrandDistributorWithBrandEntity) []*brandDistributorGrpc.BrandDistributorWithBrandEntity {
	r := make([]*brandDistributorGrpc.BrandDistributorWithBrandEntity, len(list))
	for i, item := range list {
		r[i] = f(item)
	}
	return r
}

func transformListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserIDRowEntityToPb(row sqlc.ListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserIDRow) *brandDistributorGrpc.BrandDistributorWithBrandEntity {
	return &brandDistributorGrpc.BrandDistributorWithBrandEntity{
		// brand_admin
		Id:        row.ID,
		UserId:    row.UserID,
		BrandId:   row.BrandID,
		AliasName: row.AliasName,
		Became:    sqlc.GoTimeToPBTimestamp(row.Became),
		Remark:    row.Remark.String,
		// brand
		BrandName: row.BrandName,
		BrandPic:  row.BrandPic.String,
	}
}

func mapListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserIDRowEntityToPb(list []sqlc.ListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserIDRow, f func(sqlc.ListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserIDRow) *brandDistributorGrpc.BrandDistributorWithBrandEntity) []*brandDistributorGrpc.BrandDistributorWithBrandEntity {
	r := make([]*brandDistributorGrpc.BrandDistributorWithBrandEntity, len(list))
	for i, item := range list {
		r[i] = f(item)
	}
	return r
}

/****************************************************************************************/
/*                            brand_distributorJoins entity of query                      */
/****************************************************************************************/

// ListNormalBrandDistributorWithUsersByBrandID  获取分销员及其用户信息列表
func (s *BrandAPIService) ListNormalBrandDistributorWithUsersByBrandID(ctx context.Context, req *brandDistributorGrpc.ListNormalBrandDistributorWithUsersByBrandIDRequest) (res *brandDistributorGrpc.ListNormalBrandDistributorWithUsersByBrandIDResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brand_distributorImp->ListNormalBrandDistributorWithUsersByBrandID:%v", req)

	res = &brandDistributorGrpc.ListNormalBrandDistributorWithUsersByBrandIDResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}

	q := s.dao.Q
	ts := sqlc.PBTimestampToGoTime(req.Ts)
	brandID := req.BrandId
	keyword := req.Keyword
	isKeywordEmpty := keyword == ""
	keywordLike := fmt.Sprintf("%%%s%%", keyword)

	total, err := q.CountNormalBrandDistributorWithUsersByBrandID(ctx, sqlc.CountNormalBrandDistributorWithUsersByBrandIDParams{
		Created:        ts,
		BrandID:        brandID,
		IsKeywordEmpty: isKeywordEmpty,
		Keyword:        keywordLike,
	})
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	if total == 0 {
		// 不用继续调用listfunc
		return
	}

	brandDistributorWithUsers, err := q.ListNormalBrandDistributorWithUsersByBrandID(ctx, sqlc.ListNormalBrandDistributorWithUsersByBrandIDParams{
		Limit:          req.Limit,
		Offset:         req.Offset,
		Created:        ts,
		BrandID:        brandID,
		IsKeywordEmpty: isKeywordEmpty,
		Keyword:        keywordLike,
	})
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.Total = total
	res.BrandDistributorWithUsers = mapBrandDistributorWithUserEntityToPb(brandDistributorWithUsers, transformBrandDistributorWithUserEntityToPb)
	return
}

// ListNormalBrandDistributorWithBrandsByUserID  获取分销员的分销品牌列表
func (s *BrandAPIService) ListNormalBrandDistributorWithBrandsByUserID(ctx context.Context, req *brandDistributorGrpc.ListNormalBrandDistributorWithBrandsByUserIDRequest) (res *brandDistributorGrpc.ListNormalBrandDistributorWithBrandsByUserIDResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brand_distributorImp->ListNormalBrandDistributorWithBrandsByUserID:%v", req)

	res = &brandDistributorGrpc.ListNormalBrandDistributorWithBrandsByUserIDResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	total, err := s.dao.Q.CountNormalBrandDistributorsByUserID(ctx, req.UserId)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	if total == 0 {
		// 不用继续调用listfunc
		return
	}
	arg := sqlc.ListNormalBrandDistributorWithBrandsByUserIDParams{
		Limit:  req.Limit,
		Offset: req.Offset,
		UserID: req.UserId,
	}
	brandDistributorWithBrands, err := s.dao.Q.ListNormalBrandDistributorWithBrandsByUserID(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.Total = total
	res.BrandDistributorWithBrands = mapListNormalBrandDistributorWithBrandsByUserIDRowEntityToPb(brandDistributorWithBrands, transformListNormalBrandDistributorWithBrandsByUserIDRowEntityToPb)
	return
}

// ListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserID  获取未开通分销门店的分销员的列表
func (s *BrandAPIService) ListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserID(ctx context.Context, req *brandDistributorGrpc.ListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserIDRequest) (res *brandDistributorGrpc.ListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserIDResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brand_distributorImp->ListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserID:%v", req)

	res = &brandDistributorGrpc.ListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserIDResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	userID := req.UserId
	total, err := s.dao.Q.CountNormalBrandDistributorWithBrandsOfStoreNotOpenByUserID(ctx, userID)
	if err != nil {
		return
	}
	if total == 0 {
		// 不用继续调用listfunc
		return
	}

	brandDistributorWithBrands, err := s.dao.Q.ListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserID(ctx, sqlc.ListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserIDParams{
		Limit:  req.Limit,
		Offset: req.Offset,
		UserID: userID,
	})
	if err != nil {
		return
	}
	res.Total = total
	res.BrandDistributorWithBrands = mapListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserIDRowEntityToPb(brandDistributorWithBrands, transformListNormalBrandDistributorWithBrandsOfStoreNotOpenByUserIDRowEntityToPb)
	return
}
